解决信用,仅仅有加密和解密是不够的。加密解密解决的只是传输链路的安全问题,相当于两个人说话不被窃听。可以类比成你现在生活的世界——货币的信用,是由政府在背后支撑的;购房贷款的信用,是由银行在背后支撑的;你肯购买视频网站的会员,也是由公司的信誉在背后支撑;就连比特币的信用也需要有知名人士(比如马斯克等)在不断喊话……

我想要强调的是,归根结底,信用源于我们的世界,信用的背后不是数学和算法,而是人,以及围绕人形成的组织、机构、国家等。

我们回到一个很小的问题,你在上网时候,凭什么可以相信你访问的网站没有骗你?今天我们就以这个话题为引,从 HTTPS 协议的信用角度去看互联网的整个信用体系

摘要和签名

现实的生活当中,如果想证明一份合同没有被修改过,人们会在合同上盖一个齐缝章,并附上自己的签名。签名和盖章其实是一个含义,目的是证明自己签署过某份协议,而且一经签署,协议就不能再变更。

如果想阻止一份合同被修改,最容易想到的方式是加密。合同一旦被加密了,要修改就必须原文和密文一起修改。虽然这没有解决最本质的问题——谁来提供信用。但是这样的种做法解决了一个最基础的问题。如果有人想修改合同,就必须知道密钥。

摘要算法

但是加密算法的计算量较大,而且结果通常比原文体积大。那是否有其他更好的处理方式呢?其实一个更简单的做法,就是利用摘要算法。摘要,顾名思义,和现实中文章的摘要是一样的。相当于给一篇文章,形成一个提要。只不过,计算机世界的摘要算法算出来的结果并不是对原文真的概括总结,而是一个大数字。

给计算机一篇文章,计算机用摘要算法(主要是哈希类算法)生成一个字符串,如果文章内容改变,哪怕是一个字,一个标点符号,摘要也会完全改变。和完全加密一篇文章相比,摘要的体积很小,因此非常有利于存储和传输。

通常对于一个给定的摘要算法,无论你的文章多大,有多少字节,最终生成摘要的字节数是固定的。以 MD5 摘要算法为例:

1
2
md5(1字节数据)
md5(1M数据)

无论数据多大,经过 MD5 计算后,都会形成一个 128 位的值,换算成 16 进制是 16 个字符。可见,摘要算法是比较省空间的,如果用加密算法,那么体积会和原文大小正相关。用 MD5 摘要一个 100M 的视频文件,也会形成只有 128 位的值。

摘要的价值

摘要是对原文的证明,从原文到摘要是一个不可逆的过程

通过原文可以计算出摘要,一旦原文发生变化,哪怕是一个标点符号,摘要也会发生变化。而已知一个摘要,想要反推出原文,几乎是不可能的。因为摘要和原文并不是一对一的关系,是多个原文对应一个摘要。而且,想要找到两个摘要碰撞的原文是非常困难的发生概率相当于买彩票中大奖 。而且就算黑客找到了碰撞的原文,也未必可以起到作用。当然,摘要碰撞是危险的,下面我们会讨论摘要碰撞的危害。因此,我们通常会选择碰撞难度更高的摘要算法,这里推荐你在实战中用 SHA-1 摘要算法

下面我们聊聊摘要碰撞的危害,举个具体的例子:目前多数网站用户的密码是以摘要的形式保存的。你可能会问,为什么不以原文形式保存呢?这是因为程序员会经常接触到数据库,而黑客也有可能黑进公司的数据库,因此密码以摘要显示保存更加安全,可以有效防止用户敏感数据被盗。因此,网站的设计,一般不存储用户的密码,只存储用户密码的摘要。如果网站的数据库被攻破,黑客拿到的是用户密码的摘要。拥有摘要什么也做不了,因为通过摘要找不到用户密码的原文,仍然不能登录这个网站。但是如果黑客能找到一个和密码碰撞的原文呢? 那黑客就可以正常登录了。因此摘要碰撞是非常危险的,好在目前的算法都足够安全。

摘要算法解决了以下这几个问题:

  • 为原文生成固定长度的内容证明(内容摘要);
  • 摘要无法被逆向得到原文,看上去是随机的,黑客拿到了也不知道原文;
  • 极少概率碰撞:不同的内容极大概率(绝大多数接近 100%)会生成不同的摘要。
  • 但是你要明白,摘要只是一个工具,它可以用来解决很多问题,比如说用户密码存储问题。对于互联网的信用,它还只是工具。

    签名

    摘要的另一个非常重要的用途就是签名。举个例子,张三和李四签署一份合同。

    如果张三将合同生成摘要,再用自己的私钥加密摘要,得到一个密文串,那么这个串就是张三对合同的数字签名(Digital Sign)

    张三生成好数字签名,将自己的公钥、合同原文以及数字签名交给李四保管,就基本上达成了今天我们签约双方交换合同的效果。

    你可以这样思考,数字签名是对摘要的加密,因此数字签名本身还拥有摘要能力的

    如果原文没有被修改,那么下面的条件会满足:

    1
    公钥解密(数字签名) == 签订合同时的原文摘要 == 摘要算法(当前原文) == 当前摘要

    比如原文被修改,那么可以通过重新计算摘要,对比解密后的数字签名(其实就是早先的摘要)。对张三而言,李四不知道自己私钥,因此他篡改不了自己签名的这份合同。对李四而言,张三无法抵赖自己没有签署过这份合同,因为李四可以拿着张三的公钥解密得到摘要,然后再对比合同原文的摘要。因为是张三私钥加密,如果张三的公钥能解开,那说明就是张三签署的合同。

    证书

    在上面张三和李四的例子当中还存在着一个重要的缺陷,就是张三、李四的公钥凭什么具有公信力?一份合同,张三李四都要签名,然后互相交换签名的数据。但是请你注意,这里咱们只是用到了技术的手段,或者你可以理解成这是一个数学的方式。信用本身不能用数学解决,数学只是工具。这里还存在着一个重要的缺陷,就是谁来证明,张三给李四的公钥,就是张三的公钥;李四给张三的公钥,就是李四的公钥。而谁又来证明张三和李四,是合法的两个个人,具有签署合同的权利

    信用的提供

    这里涉及的一个最基本问题是,信用必须有人提供。只有权威机构(比如公安局)可以证明张三是张三,李四是李四。同理,互联网世界也需要机构提供证书,由机构证明他们的公钥。这并不是说,张三自己不能制作自己的证书,只不过张三做的证书没有公信力。互联网中,加密算法、签名算法都是公开的,只不过张三自己制作的证书背后没有信用的支持。

    证书制作

    证书是一个身份证明文件,比如互联网中,经常会为一个域名制作证书。通常的一个域名证书会有一些基础信息:

    • 覆盖的域名
    • 证书的用途
    • 签发时间
    • 到期时间
    • 域名方的公钥
    • ...

    除了证明身份,证书还有一个重要的作用就是让其他人可以使用自己的公钥。比如自己签名的数据,就可以用自己的公钥解密对照。总的来说,你可以把这些基础信息视作文本,最重要的,就是要有权威机构对证书的签名。权威机构用自己的私钥对证书进行签名,于是证书上还需要增加 3 个信息:

    • 权威机构的名称
    • 权威机构的签名
    • 权威机构的网址

    最后这步签名操作就好像护照上要盖个章一样,有了这个权威机构的签名,证书就合法了。

    下面是拉勾的 HTTPS 证书,你可以做个对比学习:

    有一些关键信息,比如签名和公钥,虽然没有在这个图片中体现,但这些信息也是在证书中的。

    信用链的验证

    现在问题来了,张三把证书给了李四,李四拿到张三的证书,并看到某权威机构的签名。李四的第一反应就是——这个签名是权威机构的吗?比如上图中拉勾的签名,当你打开拉勾教育的时候,你相信这个证书是 GlobalSign 签发的吗?大部分同学都不知道 GlobalSign吧? 其实我也不知道这家机构。但是这不重要,用户甚至不需要理解 GlobalSign,计算机产业的底层建筑帮助大家解决了这个问题——这个被称作信用链

    当我们用 HTTPS 协议打开拉勾教育的页面时,这个证书会随着 HTTPS 的握手被下载到本地。浏览器打开证书,发现提供方式 GlobalSign。GlobalSign(Certificate Authority,CA)是一家证书颁发机构。

    浏览器并不需要理解 GlobalSign 是谁,在验证过程中,浏览器会查找操作系统中,是否已经安装了 GlobalSign 的证书。如果已经安装了,浏览器就会相信这个证书。操作系统的提供商,比如微软、苹果、谷歌总不会恶意安装非法证书砸自己的招牌。只要用户本机安装了 GlobalSign 证书,那么 GlobalSign 证书的公钥就应该可以解密网站证书的签名,得到网站证书的摘要,那么就可以信任 GlobalSign 签发的这张拉勾的证书。

    如果操作系统中没有安装 GlobalSign 的证书该怎么办呢?不要着急,这个时候,浏览器会去 GlobalSign 的网站下载证书,拿到 GlobalSign 证书后,浏览器也不确定 GlobalSign 是一个权威机构,这个时候浏览器会看 GlobalSign 证书上有没有签发方。如果有,递归进行检查签发方的证书是否安装在操作系统本地,直到找到根证书。根证书的特点是,这个机构的证书没有其他机构为它签名。只要操作系统中有根证书,那么 GlobalSign 就值得信任,因此拉勾值得信任。

    在上述过程中,操作系统的提供商起到重要的作用。操作系统安装的时候,会预装一些证书。这些证书我们称为根证书,能签发根证书的机构就是根证书提供商。根证书提供商在全球很少,通常只有信誉非常棒的机构才能担当。而且成为根证书要得到很多资质,如果中间出现问题,还会被取消资格,特别是还需要和多家操作系统提供商达成合作,比如微软、苹果、谷歌等。

    信任链的具体形式

    以上的层层证明形式,构成了一个信任链。

    一般的,信任链有 3 层。最顶层是根证书和根证书机构(Root Certificate,Root CA)。前面我们提到,根证书往往是随着操作系统安装的,特殊情况需要用户自己安装。比如说一些抓包工具,会要求用户自己安装一个根证书。

    中间的是中间证书机构,它们自己的证书是由 Root CA 签名颁发的,同时它们向最底层的终端机构提供证书。

    根证书是自签名,中间证书是根证机构书签名,终端证书(比如拉勾网)是中间证书机构签名。这样就构成了一个信任链,并且也增加了犯罪的成本。犯罪分子如果想要冒充证书,那么它的证书就需要获得中间证书提供商的签名,而获得签名需要购买证书。犯罪分子就算购买了证书,也只能购买自己域名的证书,因此无法伪装成其他网站。但要特别注意的是,如果犯罪分子设法在你的个人电脑上安装了它的根证书,那后果就严重了,它可以冒充成任何网站

    小结

    解决信用不是一个数学问题。基于信任关系塑造信用是当今社会的主流做法,比如基于社交关系的信用、基于国家机器的信用、基于公司信誉的信用……另一方面,当然工具也是必不可少的。

    摘要,是一种数学的证明,本身体积很小,还不存在密钥管理和分发问题,适合在网络环境中工作。在摘要上用私钥加密就是签名,签名可以防止数据被篡改、伪造等。在摘要和签名的基础上,可以利用原本的社会关系,让一些信用优秀的机构提供信用,这就是证书的颁发和信用链体系。

    现在你可以尝试来回答本讲关联的面试题目:为什么可以相信一个 HTTPS 网站?

    当用户用浏览器打开一个 HTTPS 网站时,会到目标网站下载目标网站的证书。接下来,浏览器会去验证证书上的签名,一直验证到根证书。如果根证书被预装,那么就会信任这个网站。也就是说,网站的信用是由操作系统的提供商、根证书机构、中间证书机构一起在担保

    思考题:

    如果公司要求你生成一个公私钥对,然后去证书机构申请证书,请问如果你丢失了这个公私钥对有什么危害?你要如何保护这个公私钥对?

    先明说说为什么会有这个问题。网站拥有者向 CA 机构申请证书时,证书请求文件中只包含公钥,不包含私钥。 证书私钥由网站保存,证书请求文件提交给 CA 机构进行认证和签名后对外公开。而大部分公司都会规定:含有敏感信息的数据不能带出公司,比如只能存放在公司的笔记本、公司的网盘、公司的服务器上,但是显然对于存储证书的场景不适用。因为私钥太敏感了,有了私钥相当于可以解密用户发送给服务器的数据,泄漏的危害性非常大。

    因此,此类证书文件通常不在办公电脑,或者公司网盘上备份。如果你自己的电脑中有备份,应该尽快删除。通常证书直接保存到安全级别较高的服务器上,只有需要使用证书的软件才能够访问。另外,如果外部的第三方服务需要用到私钥,比如 CDN,那么这里还会涉及一些特别的密钥分发技术,以及硬件加密技术,具体可以参考 Keyless SSL 和 Intel 的 QAT 方案。